package textprocessing.nlpanalysis.constituent;

import algorithm.config.HumanLanguage;
import algorithm.nlp.corenlp.TextAnnotator;
import edu.stanford.nlp.pipeline.Annotation;
import edu.stanford.nlp.trees.Tree;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by common on 2017/4/8.
 */
public class Recombinator {

    static final Logger logger = LoggerFactory.getLogger(Recombinator.class);

    //private List<SCITree> sciTrees;

    public Recombinator(){


    }


    /*
    后序遍历树，
     */
    public List<ContextItem> generate_contexts(SCITree sciTree){
        List<ContextItem> contextsItems = new ArrayList<>();

        SCITree.SCITreeNode root = sciTree.root;
        //SCITree.traversal_print(root, "");

        /*
        1） 后序遍历每棵树，变换每个节点的 contexts
        2） 获取root节点的contexts数组，返回结果
         */
        recombination(root);

        contextsItems = root.contextItems;
        return contextsItems;
    }


    private void recombination(SCITree.SCITreeNode root){
        /*
        (SCR 1)
        此处的叶子节点可能是SCITree中经过合并的
         */
        if(root.isLeaf){
            root.contexts.add(root.content);
            /*
            叶子节点的contextItems已经生成，不用改变
             */
            //ContextItem item = new ContextItem();
            //item.addTokenLast(root.originalNode);
            //item.copy( root.contextItems );
            //root.contextItems.add(item);
        }
        else{
            //String child_content = "";
            for(SCITree.SCITreeNode childNode : root.childs){
                recombination(childNode);
                //child_content += (" " + childNode.content);
            }

            /*
            (SCR 0)
             */
            if(root.nodeType == SCITree.NodeType.SUB){

                /*
                !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                 TODO ：
                 能否保证，head节点NP一定已经生成了content,
                 head节点的context是否只包含一个元素
                  */

                //root.content = root.headNode.content + child_content;
                String headContent = "";
                Tree headToken = null;
                if(root.headNode!=null) {
                    headContent = root.headNode.content;
                    headToken = root.headNode.originalNode;
                }
                root.contexts = new ArrayList<>();
                root.contextItems = new ArrayList<>();
                // UNION
                for(SCITree.SCITreeNode sub:root.childs){
                    for(String context: sub.contexts){
                        root.contexts.add(headContent + " " + context);
                    }
                    for(ContextItem item: sub.contextItems){
                        try{
                            ContextItem new_item = new ContextItem();
                            new_item.copy(item);
                            if(headToken!=null) {
                                //new_item.addTokenFirst( headToken );
                                if(root.headNode.contextItems.size() != 1){
                                    logger.error("[headNode] Multiple Context Error , Node Info \n{}", headToken.toString());
                                    logger.error("[headNode] size = {}, lael = {}", root.headNode.contextItems.size(), root.headNode.originalNode.label());
                                    throw new Exception("Context Num Error");
                                }
                                // 应该具有唯一的 context, 包含该 NP 下的所有Token
                                new_item.extendFirst(root.headNode.contextItems.get(0));
                            }
                            root.contextItems.add(new_item);
                        }catch (Exception e){
                            e.printStackTrace();
                        }

                    }
                }
            }

            /*
            (SCR 2b)  ENUM
             */
            if(root.nodeType == SCITree.NodeType.ENUM){
                root.contexts = new ArrayList<>();
                root.contextItems = new ArrayList<>();
                // UNION
                // 合并子树的结果
                for(SCITree.SCITreeNode sub:root.childs){
                    for(String context: sub.contexts){
                        root.contexts.add(context);
                    }
                    for(ContextItem item:sub.contextItems){
                        root.contextItems.add(item);
                    }
                }
            }

            /*
            (SCR 2c)  CONC
             */
            if(root.nodeType == SCITree.NodeType.CONC){
                root.contexts = new ArrayList<>();
                root.contextItems = new ArrayList<>();
                /*
                cross-product
                 */
                List<String> result = new ArrayList<>();
                List<String> temp = new ArrayList<>();
                if(root.childs.size() > 0){
                    result = root.childs.get(0).contexts;
                }
                for(int i = 1; i < root.childs.size(); i++){
                    temp = new ArrayList<>();
                    for(String context : root.childs.get(i).contexts ){
                        for(String base: result){
                            temp.add(base  + " " + context);
                        }
                    }
                    result = temp;
                }
                root.contexts = result;
                /*
                cross-product for ContextItem
                 */
                List<ContextItem> resultContexts = new ArrayList<>();
                List<ContextItem> tempContexts = new ArrayList<>();
                if(root.childs.size() > 0){
                    resultContexts = root.childs.get(0).contextItems;
                }
                for(int i = 1; i < root.childs.size(); i++){
                    tempContexts = new ArrayList<>();
                    for(ContextItem context : root.childs.get(i).contextItems ){
                        for(ContextItem base: resultContexts){
                            ContextItem new_item = new ContextItem();
                            new_item.copy( base );
                            new_item.extendLast( context );
                            //temp.add(base  + " " + context);
                            tempContexts.add( new_item );
                        }
                    }
                    resultContexts = tempContexts;
                }
                root.contextItems = resultContexts;
            }
        }
    }



    /*
    *******************************************************************************
    * UNIT TEST
     */
    public static void main(String[] args){
        //String text = "Barack Obama is the president of USA. He was a lawyer before he became the president. He loves swimming while he hate hiking. He was born in Hawaii";
        //String text = "Barack Obama is the president of USA. He loves swimming while he hate hiking. China have largest population and third area.";

        String text;
        text = "Rhubarb have medical roots and edible stalks";

        TextAnnotator textAnnotator = new TextAnnotator(HumanLanguage.ENGLISH);
        Annotation document = textAnnotator.getAnnotatedText(text);

        SCITreeGenerator generator = new SCITreeGenerator();
        List<SCITree> sciTrees = generator.getSCITreeOfDocument(document);

        Recombinator recombination = new Recombinator();

        for(SCITree tree: sciTrees){
            System.out.println("\n\nnew tree\n\n");

            recombination.generate_contexts(tree);

            System.out.println("\nPrint Root Context!\n");
            SCITree.SCITreeNode root = tree.root;
            for(String context: root.contexts){
                System.out.println(context);
            }
        }
    }
}
